
//user includes
#include "Renderer.h"
#include "Game.h"
#include "Window.h"
#include "pg2_directinput.h"
#include "Camera.h"
#include "Engine.h"


MegaEngine::Engine::Engine(Game* game, HINSTANCE hInstance, unsigned int width, unsigned int height)
{
	this->game = game;
	HWND winHandle;
	window = new Window(hInstance);
	if(window == NULL) throw "window creation error";
	window->createWindow(width, height, winHandle);
	input = new pg2::DirectInput();
	if(input == NULL) throw "Input creation error";
	if(!input->init(hInstance,window->GetWindowHandle())) throw "Input initialization error";
}

bool MegaEngine::Engine::Init()
{
	renderer = new Renderer(window->GetWindowHandle());
	
	return (renderer != NULL) && (renderer->Init()); //using lazy conditioning to make sure the renderer object was created before calling the Init method
}

bool MegaEngine::Engine::End()
{
	//window render input camera
	if(mainCamera)
		Camera::DeleteCamera();
	return true;
}

bool MegaEngine::Engine::Loop()
{
	bool bQuit = false;
	MSG kMsg;
	
	input->acquire();
	input->reset();
	mainCamera = Camera::GetCamera();

	game->Init();
	
	while(!bQuit)
	{
		// capturo el mensaje de Windows
		if (PeekMessage(&kMsg,NULL,0,0,PM_REMOVE))
		{
			switch(kMsg.message)
			{
				// si es un mensaje de salir de la aplicacion
				case WM_QUIT:
					bQuit = true;
					break;

				// si es un mensaje de presionar una tecla
				case WM_KEYDOWN:
				{
					int iKeyCode = (int)kMsg.wParam;

					switch (iKeyCode)
					{
						// si esa tecla es ESC
						case VK_ESCAPE:
   							bQuit = true;
							break;
					}
					break;
				}
			}

			// le paso el mensaje de vuelta a Windows
			TranslateMessage(&kMsg);
			DispatchMessage(&kMsg);
		}
		input->reacquire();
		if(!renderer->BeginScene())
		{
			game->End(false);
			return false;
		}
		if(!game->Loop())
		{
			game->End(false);
			return false;
		}
		if(mainCamera)
			mainCamera->Update(renderer);

		if(!renderer->EndScene())
		{
			game->End(false);
			return false;
		}
		
		bQuit = bQuit || game->IsExiting();
		
			
	}
	game->End(true);
	End();
	return true;
}

MegaEngine::Engine::~Engine()
{
	if (renderer)
		delete renderer;
	if (input)
	{
		input->unacquire();
		input->deinit();
		delete input;
	}
	if (window)
		delete window;
}

inline MegaEngine::Renderer* MegaEngine::Engine::GetRenderer()
{
	return renderer;
}

inline pg2::DirectInput* MegaEngine::Engine::GetInput()
{
	return input;
}

inline MegaEngine::Camera * MegaEngine::Engine::GetMainCamera()
{
	return mainCamera;
}